{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Implementation of Deep Convolutional GANs\n",
    "Reference: https://arxiv.org/pdf/1511.06434.pdf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Run the comment below only when using Google Colab\n",
    "# !pip install torch torchvision"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import torch\n",
    "import torchvision\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from torch.utils.data import DataLoader\n",
    "from torch.utils.data.dataset import Dataset\n",
    "from torchvision import datasets\n",
    "from torchvision import transforms\n",
    "from torchvision.utils import save_image"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import datetime\n",
    "import os, sys"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import glob"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from PIL import Image"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from matplotlib.pyplot import imshow, imsave\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "MODEL_NAME = 'DCGAN'\n",
    "DEVICE = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "IMAGE_DIM = (32, 32, 3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def get_sample_image(G, n_noise):\n",
    "    \"\"\"\n",
    "        save sample 100 images\n",
    "    \"\"\"\n",
    "    z = torch.randn(10, n_noise).to(DEVICE)\n",
    "    y_hat = G(z).view(10, 3, 28, 28).permute(0, 2, 3, 1) # (100, 28, 28)\n",
    "    result = (y_hat.detach().cpu().numpy()+1)/2.\n",
    "    return result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "class Discriminator(nn.Module):\n",
    "    \"\"\"\n",
    "        Convolutional Discriminator for MNIST\n",
    "    \"\"\"\n",
    "    def __init__(self, in_channel=1, num_classes=1):\n",
    "        super(Discriminator, self).__init__()\n",
    "        self.conv = nn.Sequential(\n",
    "            # 28 -> 14\n",
    "            nn.Conv2d(in_channel, 512, 3, stride=2, padding=1, bias=False),\n",
    "            nn.BatchNorm2d(512),\n",
    "            nn.LeakyReLU(0.2),\n",
    "            # 14 -> 7\n",
    "            nn.Conv2d(512, 256, 3, stride=2, padding=1, bias=False),\n",
    "            nn.BatchNorm2d(256),\n",
    "            nn.LeakyReLU(0.2),\n",
    "            # 7 -> 4\n",
    "            nn.Conv2d(256, 128, 3, stride=2, padding=1, bias=False),\n",
    "            nn.BatchNorm2d(128),\n",
    "            nn.LeakyReLU(0.2),\n",
    "            # \n",
    "            nn.Conv2d(128, 128, 3, stride=2, padding=1, bias=False),\n",
    "            nn.BatchNorm2d(128),\n",
    "            nn.LeakyReLU(0.2),\n",
    "            nn.AdaptiveAvgPool2d(1),\n",
    "        )        \n",
    "        self.fc = nn.Sequential(\n",
    "            # reshape input, 128 -> 1\n",
    "            nn.Linear(128, 1),\n",
    "            nn.Sigmoid(),\n",
    "        )\n",
    "    \n",
    "    def forward(self, x, y=None):\n",
    "        y_ = self.conv(x)\n",
    "        y_ = y_.view(y_.size(0), -1)\n",
    "        y_ = self.fc(y_)\n",
    "        return y_"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "class Generator(nn.Module):\n",
    "    \"\"\"\n",
    "        Convolutional Generator for MNIST\n",
    "    \"\"\"\n",
    "    def __init__(self, out_channel=1, input_size=100, num_classes=784):\n",
    "        super(Generator, self).__init__()\n",
    "        assert IMAGE_DIM[0] % 2**4 == 0, 'Should be divided 16'\n",
    "        self.init_dim = (IMAGE_DIM[0] // 2**4, IMAGE_DIM[1] // 2**4)\n",
    "        self.fc = nn.Sequential(\n",
    "            nn.Linear(input_size, self.init_dim[0]*self.init_dim[1]*512),\n",
    "            nn.ReLU(),\n",
    "        )\n",
    "        self.conv = nn.Sequential(\n",
    "            nn.Conv2d(512, 512, 3, padding=1, bias=False),\n",
    "            nn.BatchNorm2d(512),\n",
    "            nn.ReLU(),\n",
    "            # x2\n",
    "            nn.ConvTranspose2d(512, 256, 4, stride=2, padding=1, bias=False),\n",
    "            nn.BatchNorm2d(256),\n",
    "            nn.ReLU(),\n",
    "            # x2\n",
    "            nn.ConvTranspose2d(256, 128, 4, stride=2, padding=1, bias=False),\n",
    "            nn.BatchNorm2d(128),\n",
    "            nn.ReLU(),\n",
    "            # x2\n",
    "            nn.ConvTranspose2d(128, 128, 4, stride=2, padding=1, bias=False),\n",
    "            nn.BatchNorm2d(128),\n",
    "            nn.ReLU(),\n",
    "            # x2\n",
    "            nn.ConvTranspose2d(128, out_channel, 4, stride=2, padding=1, bias=False),\n",
    "            nn.Tanh(),\n",
    "        )\n",
    "        \n",
    "    def forward(self, x, y=None):\n",
    "        x = x.view(x.size(0), -1)\n",
    "        y_ = self.fc(x)\n",
    "        y_ = y_.view(y_.size(0), 512, self.init_dim[0], self.init_dim[1])\n",
    "        y_ = self.conv(y_)\n",
    "        return y_"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "class CARS(Dataset):\n",
    "    '''\n",
    "    CARS Dataset\n",
    "    You should download this dataset from below url.\n",
    "    url: https://ai.stanford.edu/~jkrause/cars/car_dataset.html\n",
    "    '''\n",
    "    def __init__(self, data_path, transform=None):\n",
    "        '''\n",
    "        Args:\n",
    "            data_path (str): path to dataset\n",
    "        '''\n",
    "        self.data_path = data_path\n",
    "        self.transform = transform\n",
    "        self.fpaths = sorted(glob.glob(os.path.join(data_path, '*.jpg')))\n",
    "        gray_lst = [266, 1085, 2176, 3048, 3439, 3469, 3539, 4577, 4848, 5177, 5502, 5713, 6947, 7383, 7693, 7774, 8137, 8144]\n",
    "        for num in gray_lst:\n",
    "            self.fpaths.remove(os.path.join(data_path, '{:05d}.jpg'.format(num)))\n",
    "        \n",
    "    def __getitem__(self, idx):\n",
    "        img = self.transform(Image.open(self.fpaths[idx]))\n",
    "        return img\n",
    "\n",
    "    def __len__(self):\n",
    "        return len(self.fpaths)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "D = Discriminator(in_channel=IMAGE_DIM[-1]).to(DEVICE)\n",
    "G = Generator(out_channel=IMAGE_DIM[-1]).to(DEVICE)\n",
    "# D.load_state_dict('D_dc.pkl')\n",
    "# G.load_state_dict('G_dc.pkl')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "transform = transforms.Compose([transforms.Resize((IMAGE_DIM[0],IMAGE_DIM[1])),\n",
    "                                transforms.ToTensor(),\n",
    "                                transforms.Normalize(mean=(0.5, 0.5, 0.5),\n",
    "                                std=(0.5, 0.5, 0.5))\n",
    "                               ]\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "dataset = CARS(data_path='/home/yangyangii/git/cars_train', transform=transform)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "batch_size = 64"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "data_loader = DataLoader(dataset=dataset, batch_size=batch_size, shuffle=True, drop_last=True, num_workers=8)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "criterion = nn.BCELoss()\n",
    "D_opt = torch.optim.Adam(D.parameters(), lr=0.001, betas=(0.5, 0.999))\n",
    "G_opt = torch.optim.Adam(G.parameters(), lr=0.001, betas=(0.5, 0.999))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "max_epoch = 100\n",
    "step = 0\n",
    "n_critic = 1 # for training more k steps about Discriminator\n",
    "n_noise = 100"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "D_labels = torch.ones([batch_size, 1]).to(DEVICE) # Discriminator Label to real\n",
    "D_fakes = torch.zeros([batch_size, 1]).to(DEVICE) # Discriminator Label to fake"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch: 0/100, Step: 0, D Loss: 1.3999, G Loss: 0.6180, Time:16:46:45\n",
      "Epoch: 3/100, Step: 500, D Loss: 1.1598, G Loss: 1.0826, Time:16:47:35\n",
      "Epoch: 7/100, Step: 1000, D Loss: 0.9844, G Loss: 0.9956, Time:16:48:25\n",
      "Epoch: 11/100, Step: 1500, D Loss: 0.9111, G Loss: 1.1050, Time:16:49:16\n",
      "Epoch: 15/100, Step: 2000, D Loss: 0.8433, G Loss: 1.1394, Time:16:50:06\n",
      "Epoch: 19/100, Step: 2500, D Loss: 1.0972, G Loss: 1.2265, Time:16:50:56\n",
      "Epoch: 23/100, Step: 3000, D Loss: 0.9124, G Loss: 1.1806, Time:16:51:47\n",
      "Epoch: 27/100, Step: 3500, D Loss: 0.7294, G Loss: 1.5435, Time:16:52:38\n",
      "Epoch: 31/100, Step: 4000, D Loss: 0.8479, G Loss: 1.4291, Time:16:53:29\n",
      "Epoch: 35/100, Step: 4500, D Loss: 0.7055, G Loss: 1.6143, Time:16:54:21\n",
      "Epoch: 39/100, Step: 5000, D Loss: 0.5880, G Loss: 1.8291, Time:16:55:12\n",
      "Epoch: 43/100, Step: 5500, D Loss: 0.7331, G Loss: 2.0989, Time:16:56:03\n",
      "Epoch: 47/100, Step: 6000, D Loss: 1.1191, G Loss: 0.4572, Time:16:56:54\n",
      "Epoch: 51/100, Step: 6500, D Loss: 0.5204, G Loss: 2.0754, Time:16:57:45\n",
      "Epoch: 55/100, Step: 7000, D Loss: 0.7635, G Loss: 1.3319, Time:16:58:38\n",
      "Epoch: 59/100, Step: 7500, D Loss: 0.7345, G Loss: 1.4658, Time:16:59:36\n",
      "Epoch: 63/100, Step: 8000, D Loss: 0.5926, G Loss: 2.2090, Time:17:00:32\n",
      "Epoch: 67/100, Step: 8500, D Loss: 0.4818, G Loss: 2.0671, Time:17:01:30\n",
      "Epoch: 71/100, Step: 9000, D Loss: 0.5194, G Loss: 2.1079, Time:17:02:28\n",
      "Epoch: 75/100, Step: 9500, D Loss: 0.4987, G Loss: 1.7474, Time:17:03:25\n",
      "Epoch: 79/100, Step: 10000, D Loss: 0.4036, G Loss: 2.1554, Time:17:04:23\n",
      "Epoch: 83/100, Step: 10500, D Loss: 1.2285, G Loss: 3.0286, Time:17:05:22\n",
      "Epoch: 87/100, Step: 11000, D Loss: 0.3730, G Loss: 2.3211, Time:17:06:19\n",
      "Epoch: 91/100, Step: 11500, D Loss: 0.3307, G Loss: 2.4072, Time:17:07:14\n",
      "Epoch: 95/100, Step: 12000, D Loss: 0.4987, G Loss: 3.4012, Time:17:08:12\n",
      "Epoch: 99/100, Step: 12500, D Loss: 0.4947, G Loss: 3.2567, Time:17:09:09\n"
     ]
    }
   ],
   "source": [
    "for epoch in range(max_epoch):\n",
    "    for idx, images in enumerate(data_loader):\n",
    "        # Training Discriminator\n",
    "        x = images.to(DEVICE)\n",
    "        x_outputs = D(x)\n",
    "        D_x_loss = criterion(x_outputs, D_labels)\n",
    "\n",
    "        z = torch.randn(batch_size, n_noise).to(DEVICE)\n",
    "        z_outputs = D(G(z))\n",
    "        D_z_loss = criterion(z_outputs, D_fakes)\n",
    "        D_loss = D_x_loss + D_z_loss\n",
    "        \n",
    "        D.zero_grad()\n",
    "        D_loss.backward()\n",
    "        D_opt.step()\n",
    "\n",
    "        if step % n_critic == 0:\n",
    "            # Training Generator\n",
    "            z = torch.randn(batch_size, n_noise).to(DEVICE)\n",
    "            z_outputs = D(G(z))\n",
    "            G_loss = criterion(z_outputs, D_labels)\n",
    "\n",
    "            D.zero_grad()\n",
    "            G.zero_grad()\n",
    "            G_loss.backward()\n",
    "            G_opt.step()\n",
    "        \n",
    "        if step % 500 == 0:\n",
    "            dt = datetime.datetime.now().strftime('%H:%M:%S')\n",
    "            print('Epoch: {}/{}, Step: {}, D Loss: {:.4f}, G Loss: {:.4f}, Time:{}'.format(epoch, max_epoch, step, D_loss.item(), G_loss.item(), dt))\n",
    "            G.eval()\n",
    "            img = get_sample_image(G, n_noise)\n",
    "            imsave('samples/{}_step{:05d}.jpg'.format(MODEL_NAME, step), img[0])\n",
    "            G.train()\n",
    "        step += 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Sample"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x7f24b366b4e0>"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f24bc1fb198>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# generation to image\n",
    "G.eval()\n",
    "imshow(get_sample_image(G, n_noise)[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x7f24b34a4f98>"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\nAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f24b360c470>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Real Image\n",
    "t = Image.open(dataset.fpaths[999])\n",
    "t = (transform(t).permute(1, 2, 0)+1)/2.\n",
    "imshow(t)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def save_checkpoint(state, file_name='checkpoint.pth.tar'):\n",
    "    torch.save(state, file_name)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Saving params.\n",
    "# torch.save(D.state_dict(), 'D_c.pkl')\n",
    "# torch.save(G.state_dict(), 'G_c.pkl')\n",
    "save_checkpoint({'epoch': epoch + 1,\n",
    "                 'D':D.state_dict(),\n",
    "                 'G':G.state_dict(),\n",
    "                 'd_optim': D_opt.state_dict(),\n",
    "                 'g_optim' : G_opt.state_dict()},\n",
    "                'dcgan.pth.tar')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
